﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Xml;

namespace StadiumEditor
{
    public partial class MainForm : Form
    {
        private Dictionary<string, List<string>> stadium = new Dictionary<string, List<string>>();
        private string path = Application.StartupPath + "\\..\\..\\..\\IGGWindowApp\\Parks";
        private PlayerLabel[] labels = new PlayerLabel[13];

        private XmlDocument m_currentStadium;

        /// <summary>
        /// Main Constructor
        /// </summary>
        public MainForm()
        {
            InitializeComponent();
            LoadStadiumsComboBox();
            InitializePlayerLabels();
        }

        /// <summary>
        /// Initialize the player labels
        /// </summary>
        private void InitializePlayerLabels()
        {
            for (int i = 0; i < 13; i++)
            {
                labels[i] = new PlayerLabel();
                labels[i].Tag = i;
                labels[i].Location = new Point(5 + (i * 32), 10 + (i * 16));
                labels[i].LabelMoved += new PlayerLabel.LabelMovedHandler(MainForm_LabelMoved);
                panelStadium.Controls.Add(labels[i]);
            }
            labels[0].Text = "Pitcher";
            labels[1].Text = "Catcher";
            labels[2].Text = "1st Base";
            labels[3].Text = "2nd Base";
            labels[4].Text = "Shortstop";
            labels[5].Text = "3nd Base";
            labels[6].Text = "Left Field";
            labels[7].Text = "Centerfield";
            labels[8].Text = "Right Field";
            labels[9].Text = "Batter";
            labels[9].BackColor = Color.LightGray;
            labels[10].Text = "Man on 1st";
            labels[10].BackColor = Color.LightGray;
            labels[11].Text = "Man on 2nd";
            labels[11].BackColor = Color.LightGray;
            labels[12].Text = "Man on 3rd";
            labels[12].BackColor = Color.LightGray;
        }

        /// <summary>
        /// Reset the labels location
        /// </summary>
        private void ResetLabelsLocation()
        {
            for (int i = 0; i < 13; i++)
            {
                labels[i].Location = new Point(5 + (i * 32), 10 + (i * 16));
            }
        }

        /// <summary>
        /// Set the labels visibility
        /// </summary>
        /// <param name="visible"></param>
        private void SetLabelsVisibility(bool visible)
        {
            for (int i = 0; i < 13; i++)
            {
                labels[i].Visible = visible;
            }
        }

        /// <summary>
        /// Manage a label movement by the user
        /// </summary>
        private void MainForm_LabelMoved(int index, int x, int y)
        {
            string currentStadium = cboStadiums.SelectedItem.ToString();
            string currentTime = cboTimes.SelectedItem.ToString();
            SaveCurrentStadiumXML(currentStadium, currentTime, index, x, y);
        }

        /// <summary>
        /// Save a position update to the current stadium xml file
        /// </summary>
        private void SaveCurrentStadiumXML(string stadium, string time, int index, int x, int y)
        {
            try
            {
                string filename = path + "\\" + stadium + ".xml";
                m_currentStadium.Load(path + "\\" + cboStadiums.SelectedItem.ToString() + ".xml");
                XmlNodeList positionsList = m_currentStadium.GetElementsByTagName("positions");

                foreach (XmlNode positionsNode in positionsList)
                {
                    if (GetAttribute(positionsNode, "time", "") == time)
                    {
                        XmlNodeList posList = positionsNode.SelectNodes("position");
                        foreach (XmlNode pos in posList)
                        {
                            int id = int.Parse(GetAttribute(pos, "id", "-1"));
                            if (id == index)
                            {
                                pos.Attributes["x"].InnerText = x.ToString();
                                pos.Attributes["y"].InnerText = y.ToString();
                            }
                        }
                        break;
                    }
                }
                m_currentStadium.Save(filename);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        /// <summary>
        /// Load the stadium pic
        /// </summary>
        private void LoadStadiumPicture()
        {
            string fileName = path + "\\" + cboStadiums.SelectedItem.ToString();
            //if (cboTimes.SelectedItem.ToString() != "day")
            //{
            fileName += "_" + cboTimes.SelectedItem.ToString() + ".jpg";
            //}
            //else
            //{
            //    fileName += ".jpg";
            //}
            try
            {
                panelStadium.BackgroundImage = new Bitmap(fileName);
            }
            catch
            {
                panelStadium.BackgroundImage = new Bitmap(path + "\\unknown.jpg");
            }
            panelStadium.Refresh();
        }

        /// <summary>
        /// Load the players position
        /// </summary>
        private void LoadPlayersPositions(string time)
        {
            m_currentStadium = new XmlDocument();
            bool timeFound = false;
            try
            {
                m_currentStadium.Load(path + "\\" + cboStadiums.SelectedItem.ToString() + ".xml");
                XmlNodeList positionsList = m_currentStadium.GetElementsByTagName("positions");

                foreach (XmlNode positionsNode in positionsList)
                {
                    if (GetAttribute(positionsNode, "time", "") == time)
                    {
                        XmlNodeList posList = positionsNode.SelectNodes("position");
                        foreach (XmlNode pos in posList)
                        {
                            int index = int.Parse(GetAttribute(pos, "id", "0"));
                            labels[index].Left = int.Parse(GetAttribute(pos, "x", "0"));
                            labels[index].Top = int.Parse(GetAttribute(pos, "y", "0"));
                            labels[index].Refresh();
                        }
                        timeFound = true;
                        break;
                    }
                }
                if (timeFound == false)
                {
                    MessageBox.Show("There are is no xml node for " + time);
                    ResetLabelsLocation();
                }
            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        /// <summary>
        /// Load the stadiums
        /// </summary>
        private void LoadStadiumsComboBox()
        {
            DirectoryInfo dirInfo = new DirectoryInfo(path);
            FileInfo[] files = dirInfo.GetFiles();
            foreach (FileInfo file in files)
            {
                if (file.Name.Contains(".xml") == false)
                {
                    string name = file.Name.Substring(0, file.Name.LastIndexOf("."));
                    string core_name = name;
                    if (name.Contains("_"))
                    {
                        core_name = name.Substring(0, file.Name.LastIndexOf("_"));
                    }
                    if (stadium.Keys.Contains(core_name) == false)
                    {
                        cboStadiums.Items.Add(core_name);
                        stadium.Add(core_name, new List<string>());
                    }
                    if (name.Contains("_"))
                    {
                        string extension = name.Substring(file.Name.LastIndexOf("_")+1);
                        stadium[core_name].Add(extension);
                    }
                }
            }
        }

        /// <summary>
        /// Manage a selection in the stadiums combo box
        /// </summary>
        private void cboStadiums_SelectedIndexChanged(object sender, EventArgs e)
        {
            cboTimes.SelectedIndex = 0;
            panelStadium.BackgroundImage = null;
            SetLabelsVisibility(false);
        }

        /// <summary>
        /// Manage a change of selection in the times combo box
        /// </summary>
        private void cboTimes_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (cboTimes.SelectedIndex > 0)
            {
                LoadStadiumPicture();
                string time = cboTimes.SelectedItem.ToString();
                if (time == "day" || time == "dusk" || time == "night")
                {
                    SetLabelsVisibility(true);
                    LoadPlayersPositions(cboTimes.SelectedItem.ToString());
                }
                else
                {
                    SetLabelsVisibility(false);
                }
            }
        }

         #region attributes utilities methods
         protected string GetAttribute(XmlNode node, string name, string ifNullValue)
         {
             if (node.Attributes[name] == null)
             {
                 return ifNullValue;
             }
             else
             {
                 return node.Attributes[name].InnerText;
             }
         }

         /// <summary>
         /// return the attribute in a safe way
         /// </summary>
         /// <param name="node"></param>
         /// <param name="name"></param>
         /// <param name="ifNullValue"></param>
         /// <returns></returns>
         protected int GetAttribute(XmlNode node, string name, int ifNullValue)
         {
             if (node.Attributes[name] == null)
             {
                 return ifNullValue;
             }
             else
             {
                 try
                 {
                     return int.Parse(node.Attributes[name].InnerText);
                 }
                 catch
                 {
                     return ifNullValue;
                 }
             }
         }

         /// <summary>
         /// return the attribute in a safe way
         /// </summary>
         protected float GetAttribute(XmlNode node, string name, float ifNullValue)
         {
             if (node.Attributes[name] == null)
             {
                 return ifNullValue;
             }
             else
             {
                 try
                 {
                     return float.Parse(node.Attributes[name].InnerText);
                 }
                 catch
                 {
                     return ifNullValue;
                 }
             }
         }

         /// <summary>
         /// return the attribute in a safe way
         /// </summary>
         /// <param name="node"></param>
         /// <param name="name"></param>
         /// <param name="ifNullValue"></param>
         /// <returns></returns>
         protected bool GetBoolAttribute(XmlNode node, string name, string condition)
         {
             if (node.Attributes[name] == null)
             {
                 return false;
             }
             else
             {
                 try
                 {
                     string check = node.Attributes[name].InnerText;
                     return check.Equals(condition);
                 }
                 catch
                 {
                     return false;
                 }
             }
         }

#endregion

    }

    public class PlayerLabel : Label
    {
        private bool isDragging = false;
        private int clickOffsetX, clickOffsetY;
        public delegate void LabelMovedHandler(int index, int x, int y);
        public event LabelMovedHandler LabelMoved;

        public PlayerLabel():base()
        {
            this.BackColor = Color.White;
            this.BorderStyle = BorderStyle.FixedSingle;
            this.Font = new System.Drawing.Font("Franklin Gothic Book", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.Location = new System.Drawing.Point(324, 216);
            this.Size = new System.Drawing.Size(80, 17);
            this.Text = "Player";
            this.TextAlign = ContentAlignment.MiddleCenter;
            this.Visible = true;
            this.MouseDown += new MouseEventHandler(PlayerLabel_MouseDown);
            this.MouseUp += new MouseEventHandler(PlayerLabel_MouseUp);
            this.MouseMove += new MouseEventHandler(PlayerLabel_MouseMove);
        }

        private void PlayerLabel_MouseMove(object sender, MouseEventArgs e)
        {
            if (isDragging == true)
            {
                this.Left = e.X + this.Left - clickOffsetX;
                this.Top = e.Y + this.Top - clickOffsetY;
            }
        }

        private void PlayerLabel_MouseUp(object sender, MouseEventArgs e)
        {
            isDragging = false;
            LabelMoved((int)this.Tag, this.Left, this.Top);
        }

        private void PlayerLabel_MouseDown(object sender, MouseEventArgs e)
        {
            isDragging = true;
            clickOffsetX = e.X;
            clickOffsetY = e.Y;
        }
    }


}
